package org.wu.framework.lazy.orm.database.jpa.repository.support;

import org.wu.framework.core.exception.AssertFactory;
import org.wu.framework.lazy.orm.core.persistence.conf.LazyTableEndpoint;
import org.wu.framework.lazy.orm.core.persistence.conf.LazyTableFieldEndpoint;
import org.wu.framework.lazy.orm.core.source.adapter.SourceFactory;
import org.wu.framework.lazy.orm.database.jpa.repository.LazyJpaRepository;
import org.wu.framework.lazy.orm.database.lambda.stream.condition.StringBasicComparison;
import org.wu.framework.lazy.orm.database.lambda.stream.lambda.LazyLambdaStream;
import org.wu.framework.lazy.orm.database.lambda.stream.wrapper.LazyWrappers;

import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

public class SimpleLazyJpaRepository<T, ID> implements LazyJpaRepository<T, ID> {

    private final LazyLambdaStream lazyLambdaStream;
    private final Class<T> domainClass;

    public SimpleLazyJpaRepository(LazyLambdaStream lazyLambdaStream, Class<T> domainClass) {
        this.lazyLambdaStream = lazyLambdaStream;
        this.domainClass = domainClass;
    }

    /**
     * 新增 多条数据
     *
     * @param entities 数据集合
     * @return 返回数据集合
     */
    @Override
    public <S extends T> Iterable<S> saveAll(Iterable<S> entities) {
        AssertFactory.notNull(entities, "entities must not be null");

        lazyLambdaStream.insertMultiple(StreamSupport.stream(entities.spliterator(), false).collect(Collectors.toList()));
        return entities;
    }

    /**
     * 查询所有数据
     *
     * @return 查询数据集合
     */
    @Override
    public Iterable<T> findAll() {
        return lazyLambdaStream.of(this.domainClass).selectList(LazyWrappers.lambdaWrapper(), this.domainClass);
    }

    /**
     * 根据ID批量查询数据
     *
     * @param ids ID集合
     * @return 返回数据集合
     */
    @Override
    public Iterable<T> findAllByIds(Iterable<ID> ids) {
        AssertFactory.notNull(ids, "ids must not be null");
        StringBasicComparison<T> in = LazyWrappers.<T>wrapper().in(getPrimaryKeyColumnName(), ids);
        return lazyLambdaStream.of(this.domainClass).selectList(in, this.domainClass);
    }

    /**
     * 根据主键ID批量删除数据
     *
     * @param ids ID集合
     */
    @Override
    public void deleteAllByIds(Iterable<? extends ID> ids) {
        AssertFactory.notNull(ids, "ids must not be null");
        StringBasicComparison<T> in = LazyWrappers.<T>wrapper().in(getPrimaryKeyColumnName(), ids);
        lazyLambdaStream.of(this.domainClass).delete(in);
    }

    /**
     * 批量删除数据
     *
     * @param entities 删除数据条件集合，删除时逐个处理
     */
    @Override
    public void deleteAll(Iterable<? extends T> entities) {
        AssertFactory.notNull(entities, "entities must not be null");
        entities.forEach(t -> lazyLambdaStream.delete(LazyWrappers.lambdaWrapperBean(t)));

    }

    /**
     * 删除所有数据
     */
    @Override
    public void deleteAll() {
        lazyLambdaStream.of(this.domainClass).delete(LazyWrappers.lambdaWrapper());
    }

    /**
     * 新增单条数据
     *
     * @param entity 新增对象
     * @return 新增对象
     */
    @Override
    public <S extends T> S save(S entity) {
        AssertFactory.notNull(entity, "entity must not be null");
        lazyLambdaStream.insert(entity);
        return entity;
    }

    /**
     * 根据ID获取对象
     *
     * @param id 主键ID
     * @return 返回对象
     */
    @Override
    public Optional<T> findById(ID id) {
        AssertFactory.notNull(id, "id must not be null");
        T t = lazyLambdaStream.of(this.domainClass).selectOne(LazyWrappers.<T>wrapper().eq(getPrimaryKeyColumnName(), id));
        return Optional.of(t);
    }

    /**
     * 通过ID判断对象是否存在
     *
     * @param id 主键ID
     * @return 布尔类型
     */
    @Override
    public boolean existsById(ID id) {
        AssertFactory.notNull(id, "id must not be null");
        return lazyLambdaStream.of(this.domainClass).exists(LazyWrappers.<T>wrapper().eq(getPrimaryKeyColumnName(), id));
    }

    /**
     * 统计数据
     *
     * @return 统计数据数量
     */
    @Override
    public long count() {
        return lazyLambdaStream.of(this.domainClass).count(LazyWrappers.<T>wrapper());
    }

    /**
     * 根据ID删除数据
     *
     * @param id 主键ID
     */
    @Override
    public void deleteById(ID id) {
        AssertFactory.notNull(id, "id must not be null");
        lazyLambdaStream.of(this.domainClass).delete(LazyWrappers.<T>wrapper().eq(getPrimaryKeyColumnName(), id));
    }

    /**
     * 删除数据 自动过滤空数据
     *
     * @param entity 删除数据条件
     */
    @Override
    public void delete(T entity) {
        AssertFactory.notNull(entity, "entity must not be null");
        lazyLambdaStream.of(this.domainClass).delete(LazyWrappers.lambdaWrapperBean(entity));
    }

    /**
     * 获取主键
     *
     * @return 主键
     */
    protected String getPrimaryKeyColumnName() {
        // 获取ID字段
        LazyTableEndpoint lazyTableEndpoint = SourceFactory.defaultAnalyzeLazyTableFromClass(this.domainClass);
        // 获取主键
        LazyTableFieldEndpoint tableId = lazyTableEndpoint.findTableId();
        return tableId.getColumnName();
    }


}
